package cn.yunyichina.provider.clinic.service.impl;

import cn.yunyichina.provider.clinic.entity.AsmBarcodePay;
import cn.yunyichina.provider.clinic.entity.AsmGeneralBarcodePay;
import cn.yunyichina.provider.clinic.entity.AsmGeneralOrderRefund;
import cn.yunyichina.provider.clinic.entity.AsmOrderRefund;
import cn.yunyichina.provider.clinic.utils.http.HttpClient;
import cn.yunyichina.provider.clinic.utils.http.HttpResponse;
import cn.yunyichina.provider.clinic.utils.http.PostParameter;
import cn.yunyichina.provider.clinic.vo.*;
import cn.yunyichina.provider.framework.annotation.validate.ValidateException;
import cn.yunyichina.provider.framework.annotation.validate.Validator;
import cn.yunyichina.provider.framework.dubbo.service.BaseService;
import cn.yunyichina.provider.framework.dubbo.service.CacheService;
import cn.yunyichina.provider.framework.dubbo.service.PayService;
import cn.yunyichina.provider.framework.utils.UUIDUtil;
import cn.yunyichina.provider.iface.entity.base.OrderExtVo;
import cn.yunyichina.provider.iface.entity.base.Org;
import cn.yunyichina.provider.iface.entity.base.OrgApp;
import cn.yunyichina.provider.iface.entity.common.Response;
import cn.yunyichina.utils.convert.JsonUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 自助扫码机
 * Created by JoeZ on 2017/2/28.
 */
@Service
public class AsmServiceImpl {

    private Logger logger = LoggerFactory.getLogger(AsmServiceImpl.class);

    private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Resource
    private Properties yaml;

    /**
     * 扫码付接口（返回二维码链接 - 限广中医使用）
     * @interfacesName: yyt.clinic.asm.barcode.pay
     * @return
     */
    public Response payAsmBarcode(String data, String sessionId){
        Response response = new Response();
        logger.info("payAsmBarcode, request data=" + data + ", sessionId=" + sessionId);
        AsmPayBarcodeRequest request = JsonUtils.parseObject(data, AsmPayBarcodeRequest.class);

        try {
            Validator.getInstance().validate(request);
        } catch (ValidateException ex) {
            logger.info("payAsmBarcode 数据校验失败:" + ex.getMessage() + "|入参:" + data + "！");
            response.setResultCodeAndMessage("13", "数据校验失败:" + ex.getMessage() + "！");
            return response;
        }

        int bizType = 0;
        switch (request.getOrderType()){
            case 1 : bizType = 1;
                break;
            case 2 : bizType = 8;
                break;
            case 3 : bizType = 2;
                break;
            case 4 : bizType = 3;
                break;
        }

        //获得org
        Org org = null;
        response = BaseService.callHumpFromInternal("yyt.base.org.by.code.get" , JsonUtils.toJsonString(request.getHospitalCode()));
        if("0".equals(response.getResultCode())){
            org = JsonUtils.parseObject(response.getResult(), Org.class);
        }else{
            response.setResultCodeAndMessage("1", "hospitalCode error! --" + request.getHospitalCode());
            return response;
        }


        //获得platform
        OrgApp orgApp = null;
        Map<String, String> map = new HashMap<>();
        map.put("org_app_code",request.getHospitalAppCode());
        response = BaseService.callHumpFromInternal("yyt.base.orgapp.get" , JsonUtils.toJsonString(map));
        if("0".equals(response.getResultCode())){
            orgApp = JsonUtils.parseObject(response.getResult(), OrgApp.class);
        }else{
            response.setResultCodeAndMessage("1", "hospitalAppCode error!");
            return response;
        }


        String payCode = "";
        String topic = "";
        if("1".equals(request.getPayMode().toString().substring(0,1))){
            payCode = "WXNATIVE";
            topic = "ASM_WECHAT_PAY";
        }else if("2".equals(request.getPayMode().toString().substring(0,1))){
            payCode = "ALIPAYPREPAY";
            topic="ASM_ALIPAY_PAY";
        }

        //入库order
        OrderExtVo order = new OrderExtVo();
        order.setId(UUIDUtil.get32UUID());
        order.setOrderNo(CacheService.generateOrderNum(bizType, 5));
        order.setOrgId(org.getId());
        order.setOrgName(org.getOrgName());
        order.setOrgCode(org.getOrgCode());
        order.setPlatformId(orgApp.getOrgId());
        order.setPlatformCode(orgApp.getOrgCode());
        order.setPlatformName(orgApp.getOrgName());
        order.setPlatformOrgAppCode(orgApp.getOrgAppCode());
        order.setPlatformOrgAppName(orgApp.getOrgAppName());
        order.setBarcode(request.getBranchCode());
        order.setDeptName(request.getDeptName());
        order.setDeptCode(request.getDeptCode());
        order.setOrderStatus((short) 1);
        order.setPayStatus((short) 1);
        order.setOrderType(request.getOrderType().shortValue());
        order.setMedicalCardType(request.getPatCardType().shortValue());
        order.setMedicalCardNo(request.getPatCardNo());
        order.setDeptCode(request.getDoctorCode());
        order.setDoctorName(request.getDoctorName());
        order.setOutOrderNo(request.getOutOrderNo());
        order.setPayMode(request.getPayMode().shortValue());
        order.setPayAmount(request.getPayAmout());
        order.setInsuranceAmount(0);
        order.setTotalAmount(order.getPayAmount() + order.getInsuranceAmount());
        order.setPayCode(payCode);
        order.setIsInsurance((short) 0);

        response = BaseService.callHumpFromInternal("yyt.base.order.add" , JsonUtils.toJsonString(order));
        if("0".equals(response.getResultCode())){
            OrderExtVo orderExtVo = JsonUtils.parseObject(response.getResult(), OrderExtVo.class);
            if(orderExtVo == null){
                response.setResultCodeAndMessage("1", "save order error!");
                return response;
            }
        }else{
            response.setResultCodeAndMessage("1", "save order error!");
            return response;
        }


        //调用公共支付统一下单接口获取二维码链接
        Map<String, String> params = new HashMap<>();
        params.put("app_code", orgApp.getOrgAppCode());
        params.put("pay_code", payCode);
        params.put("org_code", org.getOrgCode());

        String appid = "";
        response = PayService.callUnderlineFromInternal("yyt.pay.app.identity.auth", JsonUtils.toJsonString(params));
        if("0".equals(response.getResultCode())){
            appid = JsonUtils.parseObject(response.getResult(), Map.class).get("app_id").toString();
        }else{
            response.setResultCodeAndMessage("1", "get appId for appCode error!");
            return response;
        }

        params.put("app_id", appid);
        params.put("order_no", order.getOrderNo());
        params.put("pay_amount", request.getPayAmout().toString());
        params.put("desc", "扫码付");
        params.put("topic", topic);

        AsmBarcodePay asmBarcodePay = new AsmBarcodePay();
        response = PayService.callUnderlineFromInternal("yyt.pay.pay.unified", JsonUtils.toJsonString(params));
        if("0".equals(response.getResultCode())){
            map = JsonUtils.parseObject(response.getResult(), Map.class);
            asmBarcodePay.setYytOrderNo(order.getOrderNo());
            asmBarcodePay.setYytQrcode(map.get("code_url"));
            response.setResultCodeAndMessageAndResult(Response.SUCCESS_CODE , Response.SUCCESS_MESSAGE , JsonUtils.toJsonString(asmBarcodePay));
        }else{
            response.setResultCodeAndMessage("1", "pay unified error!");
            return response;
        }

        return response;
    }



    /**
     * 支付退款接口 （限广中医使用）
     * @interfacesName: yyt.clinic.asm.order.refund
     * @return
     */
    public Response refundAsmOrder(String data, String sessionId){
        Response response = new Response();
        logger.info("refundAsmOrder, request data=" + data + ", sessionId=" + sessionId);
        AsmOrderRefundRequest request = JsonUtils.parseObject(data, AsmOrderRefundRequest.class);
        Map<String, String> params = new HashMap<>();

        try {
            Validator.getInstance().validate(request);
        } catch (ValidateException ex) {
            logger.info("refundAsmOrder 数据校验失败:" + ex.getMessage() + "|入参:" + data + "！");
            response.setResultCodeAndMessage("13", "数据校验失败:" + ex.getMessage() + "！");
            return response;
        }

        //查询订单
        params.put("order_no" , request.getYytOrderNo());
        response = BaseService.callHumpFromInternal("yyt.base.order.find" , JsonUtils.toJsonString(params));
        if("0".equals(response.getResultCode())){
            OrderExtVo order = JsonUtils.parseObject(response.getResult(), OrderExtVo.class);

            Short payStatus = 7;
            if(request.getPartialOrAllrefund() == 2){
                payStatus = 8;
            }else{
                payStatus = 7;
            }

            String payCode = "";
            if("1".equals(request.getPayMode().toString().substring(0,1))){
                payCode = "WECHAT";
            }else if("2".equals(request.getPayMode().toString().substring(0,1))){
                payCode = "ALIPAY";
            }

            if("1".equals(request.getPayMode().toString().substring(0,1))){     //微信退费
                params.put("pay_code",payCode);
                params.put("app_id",order.getPayAppId());
                params.put("total_fee",String.valueOf(order.getTotalAmount()));
                params.put("refund_fee",String.valueOf(request.getRefundAmout()));
                if(StringUtils.isNotBlank(request.getOutOrderNo())){
                    params.put("pay_order_no",request.getOutOrderNo());
                }
                try {
                    response = PayService.callUnderlineFromInternal("yyt.pay.unified.refund", JsonUtils.toJsonString(params));
                    if("0".equals(response.getResultCode())){
                        Map<String, String> map = JsonUtils.parseObject(response.getResult(), Map.class);
                        String platformSerialNumber = map.get("platformSerialNumber");
                        String payTransactionId = map.get("payTransactionId");

                        order.setPayStatus(payStatus);
                        order.setOrderStatus((short) 7);
                        order.setUpdateTime(format.format(new Date()));
                        order.setRefundTime(request.getRefundTime());

                        AsmOrderRefund refund = new AsmOrderRefund();
                        refund.setAgtRefOrdnum(platformSerialNumber);
                        response.setResultCodeAndMessageAndResult(Response.SUCCESS_CODE , Response.SUCCESS_MESSAGE , JsonUtils.toJsonString(refund));
                    }else{
                        order.setPayStatus((short) 9);
                        order.setOrderStatus((short) 4);
                        logger.info(request.getYytOrderNo() +"支付退费失败..");
                        response.setResultCodeAndMessageAndResult("1", request.getYytOrderNo() + "支付退费失败..! 原因：" + response.getResultMessage(), null);
                        return response;
                    }

                    //更新订单
                    response = BaseService.callHumpFromInternal("yyt.base.order.update", JsonUtils.toJsonString(order));
                    if("0".equals(response.getResultCode())){
                        logger.info(order.getOrderNo() + "订单更新成功！");
                    }
                } catch (Exception e) {
                    logger.error("[AsmServiceImpl.refundAsmOrder]" , e);
                }

            }else if("2".equals(request.getPayMode().toString().substring(0,1))){   //支付宝退费

            }

        }else{
            response.setResultCodeAndMessage("1", "get order error!");
            return response;
        }


        return response;
    }



    /**
     * 扫码付接口（通用——返回二维码链接）
     * @interfacesName: yyt.clinic.asm.general.barcode.pay
     * @return
     */
    public Response payAsmGeneralBarcode(String data, String sessionId){
        Response response = new Response();
        logger.info("payAsmGeneralBarcode, request data=" + data + ", sessionId=" + sessionId);
        AsmGeneralPayBarcodeRequest request = JsonUtils.parseObject(data, AsmGeneralPayBarcodeRequest.class);

        try {
            Validator.getInstance().validate(request);
        } catch (ValidateException ex) {
            logger.info("payAsmGeneralBarcode 数据校验失败:" + ex.getMessage() + "|入参:" + data + "！");
            response.setResultCodeAndMessage("13", "数据校验失败:" + ex.getMessage() + "！");
            return response;
        }

        int bizType = 0;
        switch (request.getOrderType()){
            case 1 : bizType = 1;
                break;
            case 2 : bizType = 8;
                break;
            case 3 : bizType = 2;
                break;
            case 4 : bizType = 3;
                break;
        }

        try {
            //获得org
            Org org = null;
            response = BaseService.callHumpFromInternal("yyt.base.org.by.code.get" , JsonUtils.toJsonString(request.getHospitalCode()));
            if("0".equals(response.getResultCode())){
                org = JsonUtils.parseObject(response.getResult(), Org.class);
            }else{
                response.setResultCodeAndMessage("1", "hospitalCode error! --" + request.getHospitalCode());
                return response;
            }


            //获得platform
            OrgApp orgApp = null;
            Map<String, String> map = new HashMap<>();
            map.put("org_app_code",request.getAppCode());
            response = BaseService.callHumpFromInternal("yyt.base.orgapp.get" , JsonUtils.toJsonString(map));
            if("0".equals(response.getResultCode())){
                orgApp = JsonUtils.parseObject(response.getResult(), OrgApp.class);
            }else{
                response.setResultCodeAndMessage("1", "hospitalAppCode error!");
                return response;
            }


            String payCode = "";
            String topic = "";
            if("1".equals(request.getPayMode().toString().substring(0,1))){
                payCode = "WXNATIVE";
                topic = "ASM_WECHAT_PAY";
            }else if("2".equals(request.getPayMode().toString().substring(0,1))){
                payCode = "ALIPAYPREPAY";
                topic="ASM_ALIPAY_PAY";
            }

            //入库order
            OrderExtVo order = new OrderExtVo();
            order.setId(UUIDUtil.get32UUID());
            order.setOrderNo(CacheService.generateOrderNum(bizType, 5));
            order.setOrgId(org.getId());
            order.setOrgName(org.getOrgName());
            order.setOrgCode(org.getOrgCode());
            order.setPlatformId(orgApp.getOrgId());
            order.setPlatformCode(orgApp.getOrgCode());
            order.setPlatformName(orgApp.getOrgName());
            order.setPlatformOrgAppCode(orgApp.getOrgAppCode());
            order.setPlatformOrgAppName(orgApp.getOrgAppName());
            order.setBarcode(request.getBranchCode());
            order.setDeptName(request.getDeptName());
            order.setDeptCode(request.getDeptCode());
            order.setOrderStatus((short) 1);
            order.setPayStatus((short) 1);
            order.setOrderType(request.getOrderType().shortValue());
            order.setMedicalCardType(request.getPatCardType().shortValue());
            order.setMedicalCardNo(request.getPatCardNo());
            order.setDeptCode(request.getDoctorCode());
            order.setDoctorName(request.getDoctorName());
            order.setOutOrderNo(request.getOutOrderNo());
            order.setPayMode(request.getPayMode().shortValue());
            order.setPayAmount(request.getPayAmount());
            order.setAccountAmount(0);
            order.setInsuranceAmount(0);
            order.setMedicareAmount(0);
            order.setTotalAmount(request.getPayAmount());
            order.setPayCode(payCode);
            order.setIsInsurance((short) 0);

            response = BaseService.callHumpFromInternal("yyt.base.order.add" , JsonUtils.toJsonString(order));
            if("0".equals(response.getResultCode())){
                OrderExtVo orderExtVo = JsonUtils.parseObject(response.getResult(), OrderExtVo.class);
                if(orderExtVo == null){
                    response.setResultCodeAndMessage("1", "save order error!");
                    return response;
                }
            }else{
                response.setResultCodeAndMessage("1", "save order error!");
                return response;
            }


            //调用公共支付统一下单接口获取二维码链接
            Map<String, String> params = new HashMap<>();
            params.put("app_code", orgApp.getOrgAppCode());
            params.put("pay_code", payCode);
            params.put("org_code", org.getOrgCode());

            String appid = "";
            response = PayService.callUnderlineFromInternal("yyt.pay.app.identity.auth", JsonUtils.toJsonString(params));
            if("0".equals(response.getResultCode())){
                appid = JsonUtils.parseObject(response.getResult(), Map.class).get("app_id").toString();
            }else{
                response.setResultCodeAndMessage("1", "get appId for appCode error!");
                return response;
            }

            params.put("app_id", appid);
            params.put("order_no", order.getOrderNo());
            params.put("pay_amount", request.getPayAmount().toString());
            params.put("desc", "扫码付");
            params.put("topic", topic);

            AsmGeneralBarcodePay asmBarcodePay = new AsmGeneralBarcodePay();
            response = PayService.callUnderlineFromInternal("yyt.pay.pay.unified", JsonUtils.toJsonString(params));
            logger.info("payAsmGeneralBarcode自助机调用统一扫码付,返回->"+ JSON.toJSONString(response));
            if("0".equals(response.getResultCode())){
                map = JsonUtils.parseObject(response.getResult(), Map.class);
                asmBarcodePay.setOrderNo(order.getOrderNo());
                asmBarcodePay.setQrcode(map.containsKey("code_url")?map.get("code_url"):map.get("qr_code"));
                response.setResultCodeAndMessageAndResult(Response.SUCCESS_CODE , Response.SUCCESS_MESSAGE , JsonUtils.toJsonString(asmBarcodePay));
            }else{
                response.setResultCodeAndMessage("1", "pay unified error!");
                return response;
            }
        } catch (Exception e) {
            logger.error("[AsmServiceImpl.payAsmGeneralBarcode]" , e);
        }

        return response;
    }


    /**
     * 支付退款接口 （通用）
     * @interfacesName: yyt.clinic.asm.general.order.refund
     * @return
     */
    public Response refundAsmGeneralOrder(String data, String sessionId){
        Response response = new Response();
        logger.info("refundAsmGeneralOrder, request data=" + data + ", sessionId=" + sessionId);
        AsmGeneralOrderRefundRequest request = JsonUtils.parseObject(data, AsmGeneralOrderRefundRequest.class);
        Map<String, String> params = new HashMap<>();

        try {
            Validator.getInstance().validate(request);
        } catch (ValidateException ex) {
            logger.info("refundAsmGeneralOrder 数据校验失败:" + ex.getMessage() + "|入参:" + data + "！");
            response.setResultCodeAndMessage("13", "数据校验失败:" + ex.getMessage() + "！");
            return response;
        }

        //查询订单
        params.put("order_no" , request.getOrderNo());
        response = BaseService.callHumpFromInternal("yyt.base.order.find" , JsonUtils.toJsonString(params));
        if("0".equals(response.getResultCode())){
            OrderExtVo order = JsonUtils.parseObject(response.getResult(), OrderExtVo.class);

            Short payStatus = 7;
            if(request.getPartialOrAllrefund() == 2){
                payStatus = 8;
            }else{
                payStatus = 7;
            }

            String payCode = "";
            if("1".equals(request.getPayMode().toString().substring(0,1))){
                payCode = "WECHAT";
            }else if("2".equals(request.getPayMode().toString().substring(0,1))){
                payCode = "ALIPAY";
            }
            params.put("pay_code", payCode);
            params.put("app_id", order.getPayAppId());
            params.put("total_fee", String.valueOf(order.getTotalAmount()));
            params.put("refund_fee", String.valueOf(request.getRefundAmount()));

            try {
                response = PayService.callUnderlineFromInternal("yyt.pay.unified.refund", JsonUtils.toJsonString(params));
                logger.info("AsmServiceImpl.refundAsmGeneralOrder 退费返回response-->" + JsonUtils.toJsonString(response));
                if ("0".equals(response.getResultCode())) {
                    Map<String, String> map = JsonUtils.parseObject(response.getResult(), Map.class);
                    String platformSerialNumber = map.get("platformSerialNumber");
                    String payTransactionId = map.get("payTransactionId");

                    order.setPayStatus(payStatus);
                    order.setOrderStatus((short) 7);
                    order.setUpdateTime(format.format(new Date()));
                    order.setRefundTime(request.getRefundTime());

                    AsmGeneralOrderRefund refund = new AsmGeneralOrderRefund();
                    refund.setRefundPaymentDealId(platformSerialNumber);
                    response.setResultCodeAndMessageAndResult(Response.SUCCESS_CODE, Response.SUCCESS_MESSAGE, JsonUtils.toJsonString(refund));
                }else if("5021".equals(response.getResultCode())){
                    //退费异常
                    logger.info("订单退费异常..");
                    order.setPayStatus((short) 9);
                    order.setOrderStatus((short) 4);
                } else {
                    logger.info("订单退费失败..");
                    response.setResultCodeAndMessageAndResult("2", request.getOrderNo() + "支付退费失败！原因：" + JsonUtils.toJsonString(response.getResult()), null);
                    return response;
                }

                //更新订单
                response = BaseService.callHumpFromInternal("yyt.base.order.update", JsonUtils.toJsonString(order));
                if ("0".equals(response.getResultCode())) {
                    logger.info(order.getOrderNo() + "订单更新成功！");
                }
            } catch (Exception e) {
                logger.error("[AsmServiceImpl.refundAsmGeneralOrder]", e);
            }

        }else{
            response.setResultCodeAndMessage("1", "get order error!");
            return response;
        }


        return response;
    }



    /**
     * 扫码付支付结果通知接口
     * @interfacesName: yyt.clinic.asm.result.notice.payment
     * @return
     */
    public Response paymentAsmResultNotice(String data){
        Response response = new Response();
        logger.info("paymentResultNotice, request data=" + data);
        PaymentResultNoticeVoRequest request = JsonUtils.parseObject(data, PaymentResultNoticeVoRequest.class);

        JSONObject jsonRequest = new JSONObject();
        String postURL = yaml.getProperty("AsmConfig.notice_url." + request.getHospitalCode());

        logger.info(request.getHospitalCode() + "   Get post URL:" + postURL);

        if(StringUtils.isNotBlank(postURL)){

            List<PostParameter> parameters = new ArrayList<PostParameter>();
            parameters.add(new PostParameter("hospital_code" , request.getHospitalCode()));
            parameters.add(new PostParameter("branch_code" , StringUtils.isBlank(request.getBranchCode()) ? "" : request.getBranchCode()));
            parameters.add(new PostParameter("payment_deal_id" , request.getPaymentDealId()));
            parameters.add(new PostParameter("order_no" , request.getOrderNo()));
            parameters.add(new PostParameter("out_order_no" , request.getOutOrderNo()));
            parameters.add(new PostParameter("pay_status" , request.getPayStatus()));
            parameters.add(new PostParameter("pay_time" , request.getPayTime()));
            parameters.add(new PostParameter("order_type" , request.getOrderType()));
            parameters.add(new PostParameter("pay_mode" , request.getPayMode()));
            parameters.add(new PostParameter("pay_amount" , request.getPayAmount()));

            HttpResponse httpResponse = new HttpClient().post(postURL,parameters);
            if (httpResponse.getStatusCode() == 200) {
                JSONObject jsonResponse = JsonUtils.parseObject(httpResponse.getResponseAsString());
                String resultCode = jsonResponse.getString("result_code");
                String resultMessage = jsonResponse.getString("result_message");
                response.setResultCodeAndMessage(resultCode , resultMessage);
            }

        }else{
            logger.info(request.getHospitalCode() + " 无法获取 PostURL 地址..!");
            response.setResultCodeAndMessage(Response.FAILURE_CODE , request.getHospitalCode() + " 无法获取 PostURL 地址..!");
        }

        return response;
    }

}
